package cn.hacynn.nd.controller;


import cn.hacynn.nd.common.properties.JwtProperties;
import cn.hacynn.nd.common.properties.OssProperties;
import cn.hacynn.nd.common.result.Result;
import cn.hacynn.nd.common.utils.JwtUtil;
import cn.hacynn.nd.pojo.dto.*;
import cn.hacynn.nd.pojo.entity.User;
import cn.hacynn.nd.pojo.vo.STSVO;
import cn.hacynn.nd.service.UserService;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;



/**
 * @Author Hacynn
 * @Date 2024/5/24 20:25
 * @Version 1.0
 */

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 发送验证码到邮箱     注册账号
     * @param email
     * @return
     */
    @GetMapping("/email/sendCode")
    public Result sendCode(@RequestParam String email) {
        log.info("发送验证码到邮箱:{}", email);
        userService.sendCode(email);
        return Result.success();
    }

    /**
     * 使用邮箱进行登录，没有该用户则直接注册一个
     * @param emailLoginDTO
     * @return
     */
    @PostMapping("/email/login")
    public Result emailLogin(@RequestBody EmailLoginDTO emailLoginDTO, HttpServletResponse response) {
        log.info("使用邮箱进行登录，没有该用户则直接注册一个:{}", emailLoginDTO);
        User user = userService.emailLogin(emailLoginDTO);

        // 注册、登陆成功，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", user.getId());
        String jwt = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),  // jwt签名加密时使用的密钥
                jwtProperties.getUserTtl(),  // jwt过期时间
                claims);// 设置载体信息

        // 写入前端cookie中
        Cookie cookie = new Cookie(jwtProperties.getUserTokenName(), jwt);
        // 设置 Cookie 只能通过 HTTP(S) 访问，不能通过 JavaScript 访问
        //HttpOnly = false：如果 HttpOnly 属性设置为 false，则客户端脚本可以访问该 cookie。
        //HttpOnly = true：如果 HttpOnly 属性设置为 true，则客户端脚本无法访问该 cookie。这有助于防止 XSS 攻击。
        //所以要显示输入数据时，我常常会做转义  防止XSS攻击的方式之一
        // 并且应该让cookie.setHttpOnly(false);改为true
        cookie.setHttpOnly(false);
        cookie.setPath("/");
        // 设置 Cookie 的最大生存时间（单位秒）2天
        cookie.setMaxAge((int) (jwtProperties.getUserTtl() / 1000));
        // 将 Cookie 添加到响应中
        response.addCookie(cookie);
        return Result.success();
    }

    /**
     * 用户账号登录
     * @param userLoginDTO
     * @return
     */
    @PostMapping("/login")
    public Result<User> login(@RequestBody UserLoginDTO userLoginDTO, HttpServletResponse response) {
        log.info("用户登录:{}", userLoginDTO);
        User user = userService.login(userLoginDTO);
        // 登陆成功，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", user.getId());
        String jwt = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),  // jwt签名加密时使用的密钥
                jwtProperties.getUserTtl(),  // jwt过期时间
                claims);// 设置载体信息

        // 写入前端cookie中
        Cookie cookie = new Cookie(jwtProperties.getUserTokenName(), jwt);
        // 设置 Cookie 只能通过 HTTP(S) 访问，不能通过 JavaScript 访问
        cookie.setHttpOnly(false);
        cookie.setPath("/");
        // 设置 Cookie 的最大生存时间（单位秒）2天
        cookie.setMaxAge((int) (jwtProperties.getUserTtl() / 1000));
        // 将 Cookie 添加到响应中
        response.addCookie(cookie);


        return Result.success(user);
    }

    /**
     * 获取当前用户信息
     * @return
     */
    @GetMapping("/currentUser")
    public Result<User> currentUser() {
        User user = userService.currentUser();
        return Result.success(user);
    }

    /**
     * 获取当前用户bucketName
     * @return
     */
    @GetMapping("/getBucket")
    public Result<String> getBucketName() {
        String name = userService.getBucketName();
        return Result.success(name);
    }



    /**
     * 退出登录
     * @return
     */
    @PostMapping("/logout")
    public Result logout(HttpServletRequest request, HttpServletResponse response) {
        // 清除 COOKIE-TOKEN 和 JSESSIONID cookies
        Cookie cookie1 = new Cookie("COOKIE-TOKEN", null);
        cookie1.setPath("/");
        //将 Cookie 的过期时间设置为 0，这意味着浏览器会立即删除该 Cookie。
        // 实际上，这是浏览器遇到这个 Cookie 时的处理方式，它会删除已存在的同名 Cookie。
        cookie1.setMaxAge(0);
        //将 cookie1 添加到 HTTP 响应中，这样在客户端接收到该响应时，浏览器会根据 Cookie 的属性执行相应的操作，如删除指定的 Cookie。
        response.addCookie(cookie1);

        Cookie cookie2 = new Cookie("JSESSIONID", null);
        cookie2.setPath("/");
        cookie2.setMaxAge(0);
        response.addCookie(cookie2);

        return Result.success();
    }

    /**
     * 上传头像
     * @param file
     * @return
     */
    @PostMapping("/avatar")
    public Result<String> uploadAvatar(@RequestParam MultipartFile file) {
        log.info("上传头像，参数:{}", file);
        //生成访问头像的url可以直接连接到buctname直接进行上传
        String url = userService.uploadAvatar(file);
        //返回URL可以使用户直接访问到他们上传的头像，
        return Result.success(url);
    }

    /**
     * 修改昵称
     * @param name
     * @return
     */
    @PostMapping("/updateName")
    public Result updateName(@RequestParam String name) {
        log.info("修改昵称:{}", name);
        userService.updateName(name);
        //观察返回一个的结果是否成功
        return Result.success();
    }

    /**
     * 生成 STS 凭证
     * @return
     */
    @GetMapping("/sts")
    public Result<STSVO> getSTS() {
        log.info("开始生成 STS 凭证...");
        STSVO vo = userService.getSTS();
        //看生成sts的结果是否成功
        return Result.success(vo);
    }

    /**
     * 更新用户密码
     * @param updatePasswordDTO
     * @return
     */
    @PostMapping("/updatePassword")
    public Result updatePassword(@RequestBody UpdatePasswordDTO updatePasswordDTO) {
        log.info("更新用户密码:{}", updatePasswordDTO);
        userService.updatePassword(updatePasswordDTO);
        return Result.success();
    }

    /**
     * 更新用户邮箱
     * @param updateEmailDTO
     * @return
     */
    @PostMapping("/updateEmail")
    public Result updateEmail(@RequestBody UpdateEmailDTO updateEmailDTO) {
        log.info("更新用户邮箱:{}", updateEmailDTO);
        userService.updateEmail(updateEmailDTO);
        return Result.success();
    }

    /**
     * 忘记密码，修改密码
     * @param forgetPasswordDTO
     * @return
     */
    @PostMapping("/forgetPassword")
    public Result forgetPassword(@RequestBody ForgetPasswordDTO forgetPasswordDTO) {
        log.info("修改密码:{}", forgetPasswordDTO);
        userService.forgetPassword(forgetPasswordDTO);
        return Result.success();
    }

    /**
     * 忘记密钥，修改密钥
     * @param forgetSafeCodeDTO
     * @return
     */
    @PostMapping("/forgetSafeCode")
    public Result forgetSafeCode(@RequestBody ForgetSafeCodeDTO forgetSafeCodeDTO) {
        log.info("修改密钥:{}", forgetSafeCodeDTO);
        userService.forgetSafeCode(forgetSafeCodeDTO);
        return Result.success();
    }

}
